<?php 
class DomArOneToOneTestCase extends DomArTestUnitTestCase { 
	
	public function testConstruct() {
		$a = new DomArOneToOneTestClass('a');
		$c = new DomArOneToOneChildTestClass('c');
		
		$prop = $a->getProperty('aggrChild');
		$this->assertIdentical( $prop->childClassName, 'DomArOneToOneChildTestClass');
		$this->assertIdentical( $prop->className, 'DomArOneToOneTestClass' );
		$this->assertIdentical( $prop->inverse, 'aggrParent' );
		$this->assertIdentical( $prop->actAsParent, true );
		$this->assertIdentical( $prop->composition, false );
		
		$prop = $a->getProperty('child');
		$this->assertIdentical( $prop->childClassName, 'DomArOneToOneChildTestClass');
		$this->assertIdentical( $prop->className, 'DomArOneToOneTestClass' );
		$this->assertIdentical( $prop->inverse, 'parent' );
		$this->assertIdentical( $prop->actAsParent, true );
		$this->assertIdentical( $prop->composition, true );
		
		$prop = $c->getProperty('aggrParent');
		$this->assertIdentical( $prop->childClassName, 'DomArOneToOneTestClass');
		$this->assertIdentical( $prop->className, 'DomArOneToOneChildTestClass' );
		$this->assertIdentical( $prop->inverse, 'aggrChild' );
		$this->assertIdentical( $prop->actAsParent, false );
		$this->assertIdentical( $prop->composition, false );
		
		$prop = $c->getProperty('parent');
		$this->assertIdentical( $prop->childClassName, 'DomArOneToOneTestClass');
		$this->assertIdentical( $prop->className, 'DomArOneToOneChildTestClass' );
		$this->assertIdentical( $prop->inverse, 'child' );
		$this->assertIdentical( $prop->actAsParent, false );
		$this->assertIdentical( $prop->composition, false );	
	}

	public function testSimpleSave() {
		DomArOneToOneTestClass::getTable()->update();
		$a = new DomArOneToOneTestClass('a');
		$b = new DomArOneToOneChildTestClass('b');
		
		$a->child = $b;
		$this->assertIdentical( $a->child, $b );
		$this->assertIdentical( $b->parent, $a );
		
		
		$a->save();
		$this->assertObjectDatabaseValue( $b, 'parent', $a->id);
		$this->assertObjectExist( $a );
		$this->assertObjectExist( $b );
		
		
	}

	public function testSet() {
		
		DomArOneToOneTestClass::getTable()->update();
		
		$a1 = new DomArOneToOneTestClass('a');
		$a2 = new DomArOneToOneTestClass('a');
		$b = new DomArOneToOneChildTestClass('b');
		$c = new DomArOneToOneChildTestClass('c');
		$d = new DomArOneToOneChildTestClass('d');
		$e = new DomArOneToOneChildTestClass('e');
		$f = new DomArOneToOneChildTestClass('f');
		$g = new DomArOneToOneChildTestClass('g');
		
		
		// test replace inversing
		$a1->child = $b;
		
		$this->assertIdentical( $a1->child, $b );
		$this->assertIdentical( $b->parent, $a1 );
		
		$a1->child = $c;
		$this->assertIdentical( $a1->child, $c );
		$this->assertIdentical( $c->parent, $a1 );
		$this->assertIdentical( $b->parent, NULL );

		$this->assertObjectDatabaseValue( $c, 'parent', $a1->id );
		
		// test replacing saved property value
		
		$a1->save();
		
		$a1->child = $d;
		$this->assertIdentical( $a1->child, $d );
		$this->assertIdentical( $d->parent, $a1 );
		$this->assertIdentical( $c->parent, NULL );
		$this->assertObjectDatabaseValue( $c, 'parent', 0 );
		$this->assertObjectNotExist( $c );
		$this->assertObjectExist( $a1 );
		
		$a1->save();
		$this->assertObjectDatabaseValue( $c, 'parent', 0 );
		$this->assertObjectDatabaseValue( $d, 'parent', $a1->id );
		
		
		// test replacing from child side.
		
		$d->parent = $a2;
		$this->assertIdentical( $a2->child, $d );
		$this->assertIdentical( $d->parent, $a2 );
		$this->assertIdentical( $a1->child, NULL );
		$this->assertObjectDatabaseValue( $d, 'parent', 0 );
		$this->assertObjectExist( $d );
		$this->assertObjectExist( $a1 );
		
		$a2->save();
		$this->assertObjectDatabaseValue( $d, 'parent', $a2->id );
		
		
	}
	
	public function testAggrSet() {
		
		DomArOneToOneTestClass::getTable()->update();
		
		$a1 = new DomArOneToOneTestClass('a');
		$a2 = new DomArOneToOneTestClass('a');
		$e = new DomArOneToOneChildTestClass('e');
		$f = new DomArOneToOneChildTestClass('f');
		$g = new DomArOneToOneChildTestClass('g');
		
		
		// test replace inversing
		$a1->aggrChild = $e;
		
		$this->assertIdentical( $a1->aggrChild, $e );
		$this->assertIdentical( $e->aggrParent, $a1 );

		
		// test replacing aggreagtion saved property value
		
		$a1->save();
		
		$a1->aggrChild  = $f;
		
		$this->assertIdentical( $a1->aggrChild, $f );
		$this->assertIdentical( $f->aggrParent, $a1 );
		$this->assertIdentical( $e->aggrParent, NULL );
		$this->assertObjectDatabaseValue( $e, 'aggrParent', 0 );
		$this->assertObjectExist( $e );
		$this->assertObjectExist( $a1 );
		
	
		$a1->save();
		$this->assertObjectDatabaseValue( $e, 'aggrParent', 0 );
		$this->assertObjectDatabaseValue( $f, 'aggrParent', $a1->id );
		
		
		// test aggreagtion replacing from child side.
		
		$f->aggrParent = $a2;
		$this->assertIdentical( $a2->aggrChild, $f );
		$this->assertIdentical( $f->aggrParent, $a2 );
		$this->assertIdentical( $a1->aggrChild, NULL );
		$this->assertObjectDatabaseValue( $f, 'aggrParent', 0 );
		$this->assertObjectExist( $f );
		$this->assertObjectExist( $a1 );
		
		$a2->save();
		$this->assertObjectDatabaseValue( $f, 'aggrParent', $a2->id );
	
	}
	
	public function testLoad() {
		DomArOneToOneTestClass::getTable()->update();
		
		$a1 = new DomArOneToOneTestClass('a');
		$b = new DomArOneToOneChildTestClass('b');
		$c = new DomArOneToOneChildTestClass('c');
		$d = new DomArOneToOneChildTestClass('d');
		
		$a1->save();
		
		// test setting parent child to NULL if theres no child
		DomAr::flushStoredObjects();
		$this->assertIdentical( $a1->child, NULL );

		
		// preparing load tests
		$a1->child = $b;
		$a1->save();
		$this->assertObjectDatabaseValue( $b, 'parent', $a1->id );
		
		// loading from parent side
		DomAr::flushStoredObjects();
		$aa1 = DomArOneToOneTestClass::load( $a1->id );
		$aa1->name = 'aa';
		$this->assertNotIdentical( $aa1->name, $a1->name );
		
		$this->assertIdentical( $aa1->child->name, 'b' );
		
		
		// loading from child side
		DomAr::flushStoredObjects();
		
		$bb = DomArOneToOneChildTestClass::load( $b->id );
		$bb->name = 'bb';
		$this->assertNotIdentical( $bb->name, $b->name );
		
		$this->assertIdentical( $bb->parent->name, 'a' );
		
		$a1->delete();
		$b->delete();
	}
	
	public function testValidate() {
		
		$m = new DomArOneToOneTestClass('m');
		$a = new DomArOneToOneChildTestClass('a');
		$b = new DomArOneToOneChildExtTestClass('b');
		
		$p = $m->getProperty('child');
		
		$this->assertEqual( $p->validate( $m, $m ),1 );
		$this->assertEqual( $p->validate( $m, $a ),0 );
		$this->assertEqual( $p->validate( $m, $b ),0 );
		$n = 0;
		$this->assertEqual( $p->validate( $m,  $n ),0 );
		
	
	}
	
	public function testSerialize() {
		DomArOneToOneTestClass::getTable()->update();
		
		$m = new DomArOneToOneTestClass('m');
		$a = new DomArOneToOneChildTestClass('a');
		$b = new DomArOneToOneChildTestClass('b');
		
		$m->aggrChild = $a;
		$m->save();
		$m->child = $b;
		
		DomAr::flushStoredObjects();
		
		$result = DomArObject::unserialize( $m->serialize() );
		$result->name = 'nm';
		
		$this->assertNotEqual( $result->name, $m->name );
		$this->assertEqual( $result->name, $result->child->parent->name );
		$this->assertEqual( $result->access('aggrChild'), $a->id );
		$this->assertTrue( is_object($result->access('child')) );
		$this->assertIdentical( $result->access('child')->id, $b->id );
		
		
		// test if already saved child is changed. 
		$result->aggrChild->name = 'aa';
		DomAr::flushStoredObjects();
		$result2 = DomArObject::unserialize( $result->serialize()  );
		$result2->name = 'nm2';
		
		$this->assertNotEqual( $result2->name, $result->name );
		$this->assertIdentical( $result2->access('aggrChild')->id, $a->id );
		$this->assertIdentical( $result2->access('aggrChild')->name, 'aa' );
		$this->assertIdentical( $result2->access('child')->id, $b->id );

		// test if memory is not cleaned - serialized object already exists
		$result3 = DomArObject::unserialize( $result2->serialize()  );
		$result3->name = 'nm3';
		$this->assertEqual( $result3->name, $result2->name );
		
		$result3->aggrChild->delete();
		$result3->delete();
		
		
		$this->assertTableEmpty( $m->getTableName() );
		$this->assertTableEmpty( $a->getTableName() );
	}
	
	public function testSaveParent() {
		
		DomArOneToOneTestClass::getTable()->update();
		
		$a1 = new DomArOneToOneTestClass('a1');
		
		$b = new DomArOneToOneChildTestClass('b');
		$c = new DomArOneToOneChildTestClass('c');

		$a1->child = $b;
		
		$b->save();

		$this->assertTrue( $a1->id > 0);
		$this->assertObjectDatabaseValue( $b, 'parent', $a1->id );
		
	}

	public function testListeners() {
		
		DomArOneToOneListener::getTable()->update();
		
		$a = new DomArOneToOneListener();
		$b = new DomArOneToOneListener();
		$c = new DomArOneToOneListener();
		$d = new DomArOneToOneListener();
		$e = new DomArOneToOneListener();
		
		// reset A
		$a->reset();
		$b->reset();
		$c->reset();
		$d->reset();
		$e->reset();
		$this->assertIdentical( $a->beforeSetChild, 1 );
		$this->assertIdentical( $a->afterSetChild, 1 );
		$this->assertIdentical( $a->validatorChild, 1 );
		$this->assertIdentical( $a->beforeSetParent, 1 );
		$this->assertIdentical( $a->afterSetParent, 1 );
		$this->assertIdentical( $a->validatorParent, 1 );
		
		$this->assertIdentical( $a->beforeSetChildCount, 0 );
		$this->assertIdentical( $a->afterSetChildCount, 0 );
		$this->assertIdentical( $a->validatorChildCount, 0 );
		$this->assertIdentical( $a->beforeSetParentCount, 0 );
		$this->assertIdentical( $a->afterSetParentCount, 0 );
		$this->assertIdentical( $a->validatorParentCount, 0 );

		
		// -------------------------------
		// ADD ITEM (unsaved)
		// -------------------------------
		$a->item = $b;
		$this->assertIdentical( $a->beforeSetChild, 0 );
		$this->assertIdentical( $a->afterSetChild, 0 );
		$this->assertIdentical( $a->validatorChild, 0 );
		$this->assertIdentical( $b->beforeSetParent, 0 );
		$this->assertIdentical( $b->afterSetParent, 0 );
		$this->assertIdentical( $b->validatorParent, 0 );
		
		$this->assertIdentical( $a->beforeSetChildCount, 1 );
		$this->assertIdentical( $a->afterSetChildCount, 1 );
		$this->assertIdentical( $a->validatorChildCount, 1 );
		$this->assertIdentical( $a->beforeSetParentCount, 0 );
		$this->assertIdentical( $a->afterSetParentCount, 0 );
		$this->assertIdentical( $a->validatorParentCount, 0 );
		
		$this->assertIdentical( $b->beforeSetChildCount, 0 );
		$this->assertIdentical( $b->afterSetChildCount, 0 );
		$this->assertIdentical( $b->validatorChildCount, 0 );
		$this->assertIdentical( $b->beforeSetParentCount, 1 );
		$this->assertIdentical( $b->afterSetParentCount, 1 );
		$this->assertIdentical( $b->validatorParentCount, 1 );
		
		// -------------------------------
		// REMOVE ITEM (unsaved)
		// -------------------------------
		$a->reset();
		$b->reset();
		$a->item = NULL;
		$this->assertIdentical( $a->beforeSetChild, 0 );
		$this->assertIdentical( $a->afterSetChild, 0 );
		$this->assertIdentical( $a->validatorChild, 0 );
		$this->assertIdentical( $b->beforeSetParent, 0 );
		$this->assertIdentical( $b->afterSetParent, 0 );
		$this->assertIdentical( $b->validatorParent, 0 );
		
		$this->assertIdentical( $a->beforeSetChildCount, 1 );
		$this->assertIdentical( $a->afterSetChildCount, 1 );
		$this->assertIdentical( $a->validatorChildCount, 1 );
		$this->assertIdentical( $a->beforeSetParentCount, 0 );
		$this->assertIdentical( $a->afterSetParentCount, 0 );
		$this->assertIdentical( $a->validatorParentCount, 0 );
		
		$this->assertIdentical( $b->beforeSetChildCount, 0 );
		$this->assertIdentical( $b->afterSetChildCount, 0 );
		$this->assertIdentical( $b->validatorChildCount, 0 );
		$this->assertIdentical( $b->beforeSetParentCount, 1 );
		$this->assertIdentical( $b->afterSetParentCount, 1 );
		$this->assertIdentical( $b->validatorParentCount, 1 );
		

		// -------------------------------
		// ADD ITEM (saved)
		// -------------------------------
		$a->save();
		$d->save();
		$a->reset();
		$d->reset();
		$this->assertTrue( $a->id > 0);
		$this->assertTrue( $d->id > 0);
		$a->item = $d;
		
		$this->assertIdentical( $a->beforeSetChild, 0 );
		$this->assertIdentical( $a->afterSetChild, 0 );
		$this->assertIdentical( $a->validatorChild, 0 );
		$this->assertIdentical( $d->beforeSetParent, 0 );
		$this->assertIdentical( $d->afterSetParent, 0 );
		$this->assertIdentical( $d->validatorParent, 0 );
		
		$this->assertIdentical( $a->beforeSetChildCount, 1 );
		$this->assertIdentical( $a->afterSetChildCount, 1 );
		$this->assertIdentical( $a->validatorChildCount, 1 );
		$this->assertIdentical( $a->beforeSetParentCount, 0 );
		$this->assertIdentical( $a->afterSetParentCount, 0 );
		$this->assertIdentical( $a->validatorParentCount, 0 );
		
		$this->assertIdentical( $d->beforeSetChildCount, 0 );
		$this->assertIdentical( $d->afterSetChildCount, 0 );
		$this->assertIdentical( $d->validatorChildCount, 0 );
		$this->assertIdentical( $d->beforeSetParentCount, 1 );
		$this->assertIdentical( $d->afterSetParentCount, 1 );
		$this->assertIdentical( $d->validatorParentCount, 1 );

		
		// -------------------------------
		// REMOVE ITEM (saved) (child side)
		// -------------------------------
		$a->reset();
		$d->reset();
		$a->item = NULL;
		
		$this->assertIdentical( $a->beforeSetChild, 0 );
		$this->assertIdentical( $a->afterSetChild, 0 );
		$this->assertIdentical( $a->validatorChild, 0 );
		$this->assertIdentical( $d->beforeSetParent, 0 );
		$this->assertIdentical( $d->afterSetParent, 0 );
		$this->assertIdentical( $d->validatorParent, 0 );
		
		$this->assertIdentical( $a->beforeSetChildCount, 1 );
		$this->assertIdentical( $a->afterSetChildCount, 1 );
		$this->assertIdentical( $a->validatorChildCount, 1 );
		$this->assertIdentical( $a->beforeSetParentCount, 0 );
		$this->assertIdentical( $a->afterSetParentCount, 0 );
		$this->assertIdentical( $a->validatorParentCount, 0 );
		
		$this->assertIdentical( $d->beforeSetChildCount, 0 );
		$this->assertIdentical( $d->afterSetChildCount, 0 );
		$this->assertIdentical( $d->validatorChildCount, 0 );
		$this->assertIdentical( $d->beforeSetParentCount, 1 );
		$this->assertIdentical( $d->afterSetParentCount, 1 );
		$this->assertIdentical( $d->validatorParentCount, 1 );
		
	}
}
?>